/**
自定义一个简单的map
*/

package main

import (
	"fmt"
	"math/rand"
	"strconv"
)

type Map struct {
	count   int
	c       uint8 // cap
	buckets []*bucket
}

type bucket struct {
	k    string
	v    any
	next *bucket
}

func NewMap() *Map {
	c := 1 << 3
	return &Map{
		count:   0,
		c:       uint8(c),
		buckets: make([]*bucket, c, c),
	}
}

func (m *Map) getHash(k string) uint8 {
	if k == "" {
		return 0
	}
	data := []byte(k)
	return data[0]
}

func (m *Map) index(k string) uint8 {
	hash := m.getHash(k)
	return hash % m.c
}

func (m *Map) Put(k string, v any) {
	index := m.index(k)
	b := m.buckets[index]
	if b != nil {
		tmp := b
		for tmp != nil {
			if tmp.k == k {
				tmp.v = v
				return
			}
			tmp = tmp.next
		}
	} else {
		m.buckets[index] = &bucket{k: k, v: v}
		m.count++
		return
	}

	tail := b
	for tail.next != nil {
		tail = tail.next
	}
	tail.next = &bucket{k: k, v: v}
	m.count++
}

func (m *Map) Get(k string) any {
	index := m.index(k)
	b := m.buckets[index]
	if b == nil {
		return nil
	}

	tmp := b
	for tmp != nil {
		if tmp.k == k {
			return tmp.v
		}
		tmp = tmp.next
	}
	return nil
}

func (m *Map) Count() int {
	return m.count
}

func main() {
	var m = NewMap()
	for i := 1; i <= 100; i++ {
		m.Put(strconv.Itoa(rand.Int()), i*100)
		m.Put(strconv.Itoa(i), i*100)
	}

	fmt.Println(m.Count())

	fmt.Println(m.Get("1"))
	fmt.Println(m.Get("12"))
	fmt.Println(m.Get("19"))
	fmt.Println(m.Get("user"))
}
